package apollo.generator.modules.service.impl;

import apollo.generator.common.utils.*;
import apollo.generator.config.PreferenceConfig;
import apollo.generator.modules.entity.ColumnEntity;
import apollo.generator.modules.entity.DataBaseConfigEntity;
import apollo.generator.modules.entity.PreferenceEntity;
import apollo.generator.modules.entity.TableEntity;
import apollo.generator.modules.entity.vo.DataBasePageVO;
import apollo.generator.modules.service.DataBaseConfigService;
import apollo.generator.modules.service.GenerateService;
import apollo.generator.modules.service.PreferenceService;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;

/**
 * <Description>
 * 实现
 * @author Jun Lee
 * @version 1.0
 * @createDate 2020/07/02 15:58
 * @see apollo.generator.modules.service.impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class GenerateServiceImpl implements GenerateService {

    @Autowired
    private DataBaseConfigService dataBaseConfigService;
    @Autowired
    private PreferenceService preferenceService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private PreferenceConfig preferenceConfig;

    @Override
    public PageUtils selectDataBasePage(Map<String, Object> params) throws Exception {
        String key = MapUtil.getStr(params, "key");
        Integer page = MapUtil.getInt(params, "page");
        Integer limit = MapUtil.getInt(params, "limit");
        //查询当前启用的数据库
        DataBaseConfigEntity enableDataBase = dataBaseConfigService.selectEnableDataBase();
        ArrayList<DataBasePageVO> dataBasePages = DataBaseUtils.getDataBasePages(enableDataBase,key);

        //手动分页
        long skip = (page - 1) * limit;
        List<DataBasePageVO> result = dataBasePages.stream().skip(skip).limit(limit).collect(Collectors.toList());
        PageUtils resultPage = new PageUtils(result,dataBasePages.size(),limit,page);
        return resultPage;
    }

    @Override
    public PageUtils selectTablePage(Map<String, Object> params) throws Exception {
        String dataBaseName = MapUtil.getStr(params, "dataBaseName");
        String key = MapUtil.getStr(params, "key");
        Integer page = MapUtil.getInt(params, "page");
        Integer limit = MapUtil.getInt(params, "limit");

        //获取缓存中的数据库信息
        DataBaseConfigEntity configEntity = null;
        String database = redisUtils.get(RedisKeys.getSysDataBaseConfigKey(LoginUtils.getUserId()));
        if (ObjectUtil.isNull(database)) {
            configEntity = dataBaseConfigService.selectEnableDataBase();
        }else{
            configEntity = JSON.parseObject(database, DataBaseConfigEntity.class);
        }
        ArrayList<TableEntity> tablePages = DataBaseUtils.selectTablePage(configEntity, dataBaseName, key);

        //手动分页
        long skip = (page - 1) * limit;
        List<TableEntity> result = tablePages.stream().skip(skip).limit(limit).collect(Collectors.toList());
        PageUtils resultPage = new PageUtils(result,tablePages.size(),limit,page);
        return resultPage;
    }

    @Override
    public ArrayList<TableEntity> selectTable(Map<String, Object> params) throws Exception {
        String dataBaseName = MapUtil.getStr(params, "dataBaseName");

        //获取缓存中的数据库信息
        DataBaseConfigEntity configEntity = null;
        String database = redisUtils.get(RedisKeys.getSysDataBaseConfigKey(LoginUtils.getUserId()));
        if (ObjectUtil.isNull(database)) {
            configEntity = dataBaseConfigService.selectEnableDataBase();
        }else{
            configEntity = JSON.parseObject(database, DataBaseConfigEntity.class);
        }
        ArrayList<TableEntity> tablePages = DataBaseUtils.selectTablePage(configEntity, dataBaseName, null);
        return tablePages;
    }

    @Override
    public byte[] generateCode(Map<String, Object> params) throws Exception {
        String tables = MapUtil.getStr(params, "tables");
        String dataBaseName = MapUtil.getStr(params, "dataBaseName");

        String database = redisUtils.get(RedisKeys.getSysDataBaseConfigKey(LoginUtils.getUserId()));
        DataBaseConfigEntity entity = JSON.parseObject(database, DataBaseConfigEntity.class);
        //查询偏好配置
        PreferenceEntity preference = preferenceService.selectEnablePreference();
        if (ObjectUtil.isNull(preference)) {
            preference = new PreferenceEntity();
            BeanUtils.copyProperties(preferenceConfig,preference);
        }

        //代码生成
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String table : tables.split(",")) {
            TableEntity oneTable = DataBaseUtils.getOneTable(entity, dataBaseName, table);
            ArrayList<ColumnEntity> columns = DataBaseUtils.selectColumns(entity, dataBaseName, table);

            GenerateUtils.generatorCode(oneTable,columns,zip,preference);
        }

        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }
}
